package nl.weeaboo.sh.danmaku;

import nl.weeaboo.sh.danmaku.commands.TAngle;
import nl.weeaboo.sh.danmaku.commands.TAngleInc;
import nl.weeaboo.sh.danmaku.commands.TAngleTo;
import nl.weeaboo.sh.danmaku.commands.TDestroy;
import nl.weeaboo.sh.danmaku.commands.THp;
import nl.weeaboo.sh.danmaku.commands.TPos;
import nl.weeaboo.sh.danmaku.commands.TPower;
import nl.weeaboo.sh.danmaku.commands.TSolid;
import nl.weeaboo.sh.danmaku.commands.TSpeed;
import nl.weeaboo.sh.danmaku.commands.TSplit;
import nl.weeaboo.sh.danmaku.commands.TVisible;
import nl.weeaboo.sh.danmaku.commands.TWait;
import nl.weeaboo.sh.view.CharaImage;
import nl.weeaboo.sh.view.anim.Animation;
import nl.weeaboo.sh.view.anim.AnimationFrame;

public class SpellUtil {

	public static Spell[] copyOfRange(Spell t[], int offset) {
		Spell res[] = new Spell[t.length - offset];
		for (int n = offset; n < t.length; n++) {
			res[n] = t[n].clone();
		}
		return res;
	}
	
	public static ShotModel create(Universe u, CharaImage i, int colType, SpellBook sb) {
		Animation anim = new Animation();
		anim.addFrame(new AnimationFrame(i, 1000000000));
		return create(u, anim, colType, sb);
	}
	public static ShotModel create(Universe u, Animation anim, int colType, SpellBook sb) {
		ShotModel s = new ShotModel(anim, colType, sb);
		u.addShot(s);
		return s;
	}
	public static SpellBook chain(Spell... t) {
		return new SpellBook(t, 1);
	}
	
	public static Spell tAngle(float a) { return new TAngle(a); }
	public static Spell tAngleInc(float a) { return new TAngleInc(a); }
	public static Spell tAngleTo(float ta, float ainc) { return new TAngleTo(ta, ainc); }
	public static Spell tSpeed(float s) { return new TSpeed(s); }
	public static Spell tPos(float x, float y) { return new TPos(x, y); }	
	public static Spell tSplit(int copies) { return new TSplit(copies); }	
	public static Spell tHp(int hp) { return new THp(hp); }	
	public static Spell tPower(int p) { return new TPower(p); }	
	public static Spell tSolid(boolean s) { return new TSolid(s); }	
	public static Spell tWait(int t) { return new TWait(t); }	
	public static Spell tDestroy() { return new TDestroy(); }	
	public static Spell tVisible(boolean v) { return new TVisible(v); }	
	
	public static float SIN_LUT[];
	
	static {
		SIN_LUT = new float[512];
		for (int n = 0; n < 512; n++) {
			SIN_LUT[n] = (float)Math.sin(n * Math.PI / 256f);
		}
	}
	
	public static float fastSin(int angle) { return SIN_LUT[angle & 511]; }
	public static float fastCos(int angle) { return SIN_LUT[(angle+128) & 511]; }
	public static float fastSin(float angle) {
		int a = (int)Math.floor(angle);
		float prev = fastSin(a);
		float next = fastSin(a + 1);
		
		float result = prev + (next-prev) * Math.abs(angle - a);		
		return result;
	}
	public static float fastCos(float angle) {
		return fastSin(angle+128f);
	}	

	public static float angleTo(float x0, float y0, float x1, float y1) {
		return 128f + 256f * (float)(Math.atan2(y1-y0, x1-x0) / Math.PI);		
	}
	
	/** transforms [0-511] to [0-359] */
	public static float angleToDegrees(float a) {
		return (-360f * a) / 512f;
	}
	
	public static float dist(float x0, float y0, float x1, float y1) {
		return (float)Math.sqrt(distSq(x0, y0, x1, y1));
	}
	public static float distSq(float x0, float y0, float x1, float y1) {
		float dx = x1-x0;
		float dy = y1-y0;
		return dx*dx + dy*dy;
	}
	
}
